package handler

import (
	"context"
	"github.com/astaxie/beego/logs"
	"github.com/astaxie/beego/orm"
	"github.com/garyburd/redigo/redis"
	"ihome/models"
	"ihome/utils"
	"math/rand"
	"reflect"
	"strconv"
	"time"

	"github.com/micro/go-micro/util/log"

	getSmsCd "ihome/proto/getSmsCd"
)

type GetSmsCd struct{}

// Call is a single request handler called via client.Call or the generated client code
func (e *GetSmsCd) SrvGetSmsCd(ctx context.Context, req *getSmsCd.Request, rsp *getSmsCd.Response) error {
	logs.Info("获取短信验证码 GetSmsCd /api/v1.0/smscode/:mobile")

	rsp.Code = utils.RecodeOk
	rsp.Msg = utils.RecodeText(rsp.Code)

	// 判断用户是否已存在
	o := orm.NewOrm()
	user := models.User{Mobile: req.Mobile}
	err := o.Read(&user)
	if err == nil {
		logs.Info("用户已存在")
		rsp.Code = utils.RecodeUserExist
		rsp.Msg = utils.RecodeText(rsp.Code)
		return nil
	}

	// 通过uuid查找图片验证码的值进行对比
	bm, err := utils.NewCache()
	if err != nil {
		logs.Info("redis连接失败", err)
		rsp.Code = utils.RecodeDberr
		rsp.Msg = utils.RecodeText(rsp.Code)
		return nil
	}
	uuid := bm.Get(req.Uuid)
	if uuid == nil {
		logs.Info("redis获取失败", err)
		rsp.Code = utils.RecodeDberr
		rsp.Msg = utils.RecodeText(rsp.Code)
		return nil
	}
	logs.Info(reflect.TypeOf(uuid), uuid)
	uuid_str, _ := redis.String(uuid, nil)
	if uuid_str != req.Imagestr {
		logs.Info("图片验证码错误", err)
		rsp.Code = utils.RecodeDataerr
		rsp.Msg = utils.RecodeText(rsp.Code)
		return nil
	}

	// 创建验证码
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	code := r.Intn(9999) + 1001

	// 调用服务商发送验证码
	// TODO:暂时不做

	// 将短信验证码缓存起来
	err = bm.Put(req.Mobile, strconv.Itoa(code), time.Second*300)

	logs.Info("手机号:%s的短信验证码是:%d",req.Mobile, code)

	return nil
}

// Stream is a server side stream handler called via client.Stream or the generated client code
func (e *GetSmsCd) Stream(ctx context.Context, req *getSmsCd.StreamingRequest, stream getSmsCd.GetSmsCd_StreamStream) error {
	log.Logf("Received GetSmsCd.Stream request with count: %d", req.Count)

	for i := 0; i < int(req.Count); i++ {
		log.Logf("Responding: %d", i)
		if err := stream.Send(&getSmsCd.StreamingResponse{
			Count: int64(i),
		}); err != nil {
			return err
		}
	}

	return nil
}

// PingPong is a bidirectional stream handler called via client.Stream or the generated client code
func (e *GetSmsCd) PingPong(ctx context.Context, stream getSmsCd.GetSmsCd_PingPongStream) error {
	for {
		req, err := stream.Recv()
		if err != nil {
			return err
		}
		log.Logf("Got ping %v", req.Stroke)
		if err := stream.Send(&getSmsCd.Pong{Stroke: req.Stroke}); err != nil {
			return err
		}
	}
}
